package com.yonyou.hxjy.service.dingtalk.Impl.toysImpl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.yonyou.hxjy.dao.ProcessinstanceMapper;
import com.yonyou.hxjy.entity.ProcessInstance;
import com.yonyou.hxjy.enums.DingDingComponent;
import com.yonyou.hxjy.service.dingtalk.DingtalkNewExpenseClaimToYs;
import com.yonyou.hxjy.service.dingtalk.DingtalkProcessInstanceToYs;
import com.yonyou.hxjy.service.dingtalk.Impl.YsDataGetService;
import com.yonyou.hxjy.utils.RedisUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class DingtalkNewExpenseClaimToYsImpl implements DingtalkNewExpenseClaimToYs {

    @Autowired
    private YsDataGetService ysDataGetService;

    @Autowired
    private DingtalkProcessInstanceToYs defaultDataService;

    private static final Logger logger = LoggerFactory.getLogger(DingtalkNewExpenseClaimToYs.class);

    /**
     * 费用报销新数据结构资金收款单保存到Ys中
     * @param jsonObjectList
     * @return
     */
    @Override
    public List<JSONObject> newExpenseClaim_toYsJson(List<JSONObject> jsonObjectList) {

//        List<JSONObject> filterReviewer = defaultDataService.filter_Reviewer(jsonObjectList);

        List<JSONObject> ysJsonResponseList = new ArrayList<>(); //返回结果列表
        Map<String, Object> dataMap; //参数汇总
        //获取银行列表
        List<JSONObject> bankList = ysDataGetService.getBankDetailsMessage();
        //发票主体
        //遍历ID集合构建参数
        for (JSONObject jsonObject : jsonObjectList) {
            String orgName = "";
            //保存类型
            String saveType = "";
            //单据id
            String businessId = "";
            //总金额(转成BigDecimal类型)
            BigDecimal totalAccount = BigDecimal.ZERO;
            //总税额
            BigDecimal totalSE = BigDecimal.ZERO;
            //尾插税额
            BigDecimal lastSE = BigDecimal.ZERO;

            String expenseitem_code="";

            String description="";

            String enterprisebankaccount_code="";
            try {
                //获取审批实例业务编号
                businessId = jsonObject.getJSONObject("result").getStr("businessId");
                JSONArray jsonArrayTasks = jsonObject.getJSONObject("result").getJSONArray("tasks");
                //审批id对象
                ProcessInstance processInstance = defaultDataService.getProcessInstance(jsonArrayTasks);

                dataMap = new HashMap<>();
                //构建资金付款主表参数
                Map <String,Object> paramMap = new HashMap<>();
                //String isoDateTime = jsonObject.getJSONObject("result").getStr("finishTime");
                paramMap.put("vouchdate",dealTime(jsonObject.getJSONObject("result").getStr("createTime"))); //日期
                paramMap.put("exchangeRateType_code",defaultDataService.EXCHANGE_RATE_TYPE_CODE); //汇率类型
                paramMap.put("exchRate",defaultDataService.EXCH_RAGE); //汇率
                paramMap.put("currency_code",defaultDataService.CURRENCY_CODE); //币种ID
                paramMap.put("description",businessId); //审批单据号
                paramMap.put("code",businessId); //审批单据号
                paramMap.put("_status","Insert"); //动作

                //构建资金付款单子表参数
                List<Map<String, Object>> fundPaymentBList = new ArrayList<>();
                Map<String, Object> fundPaymentBItem = new HashMap<>();
                fundPaymentBItem.put("quickType_code", defaultDataService.QUICK_TYPE_CODE[0]); // 款项类型(费用)
                fundPaymentBItem.put("settlestatus", "1"); // 结算方式
                fundPaymentBItem.put("caobject", 4); // 付款对象
                fundPaymentBItem.put("oppositeobjectname", "无"); // 收款对象单位
                fundPaymentBItem.put("_status", "Insert"); // 动作
                fundPaymentBItem.put("operator_code", jsonObject.getJSONObject("result").getStr("originatorUserId")); // 动作



                List<JSONObject> jsonArray = jsonObject.getJSONObject("result").getJSONArray("formComponentValues").toList(JSONObject.class);
                //组织以及收款账户、付款账户判定
                //发票主体
                List<JSONObject> ORG_BELONG = jsonArray.stream()
                        .filter(json -> DingDingComponent.ORG_BELONG.equals(json.getStr("id")))
                        .collect(Collectors.toList());
                //其他主体
                List<JSONObject> ORG_OTHER = jsonArray.stream()
                        .filter(json -> DingDingComponent.ORG_OTHER.equals(json.getStr("id")))
                        .collect(Collectors.toList());
                //是否冲销
                List<JSONObject> iscxList = jsonArray.stream()
                        .filter(json -> DingDingComponent.ISCX.equals(json.getStr("id")))
                        .collect(Collectors.toList());

                if(ORG_BELONG.size()>0){
                    JSONObject belong = ORG_BELONG.get(0);
                    if("其他主体".equals(belong.getStr("value"))){
                        if(ORG_OTHER.size()>0){
                            JSONObject other = ORG_OTHER.get(0);
                            orgName = other.getStr("value");
                        }
                    }else{
                        orgName = belong.getStr("value");
                    }
                }
                if(!orgName.isEmpty()){
                    String uitCodeKey = "组织名称:" + orgName;
                    String uitCode = (String) RedisUtils.get(uitCodeKey);
                    //不存在发送请求获取组织编码
                    if (StringUtils.isEmpty(uitCode)){
                        //根据组织名称获取code
                        uitCode = ysDataGetService.getOrgUitCode(orgName);
                        RedisUtils.set(uitCodeKey, uitCode);
                    }
                    if (uitCode!=null && !uitCode.isEmpty()){
                        paramMap.put("accentityRaw_code",uitCode ); //会计主体code
                        paramMap.put("accentity_code", uitCode); //资金组织code
                        paramMap.put("org_code", uitCode); //业务组织code
                        //获取默认银行数据
                        if(iscxList.size()>0){
                            JSONObject iscx = iscxList.get(0);
                            if(!iscx.getStr("value").equals("否")){
                                enterprisebankaccount_code="不付款";
                                if(iscx.getStr("value").equals("借款")){
                                    fundPaymentBItem.put("quickType_code", defaultDataService.QUICK_TYPE_CODE[4]); // 款项类型(费用)
                                }else if(iscx.getStr("value").equals("备用金")){
                                    fundPaymentBItem.put("quickType_code", defaultDataService.QUICK_TYPE_CODE[5]); // 款项类型(费用)
                                }
                            }else{
                                enterprisebankaccount_code = defaultDataService.getBankCode(orgName,bankList);
                            }
                        }
                        if (enterprisebankaccount_code!=null && !enterprisebankaccount_code.isEmpty()){
                            paramMap.put("enterprisebankaccount_code",enterprisebankaccount_code);// 企业银行账户编码
                            fundPaymentBItem.put("enterprisebankaccount_code", enterprisebankaccount_code); // (子表)企业银行账户编码
                        }else {
                            throw new RuntimeException("{error:\"获取企业银行账号失败-费用报销审批单"+businessId+"中默认银行账号不存在！！！\"}");
                        }
                    }else {
                        throw new RuntimeException("{error:\"获取组织code失败-费用报销审批单"+businessId+"中付款组织单元不存在！！！\"}");
                    }

                }else{
                    throw new RuntimeException("{error:\"费用报销审批单:"+businessId+"中未配置发票主体！！！\"}");
                }

                //报销金额
                List<JSONObject> moneyList = jsonArray.stream()
                        .filter(json -> DingDingComponent.MONEY.equals(json.getStr("id")))
                        .collect(Collectors.toList());
                if(moneyList.size()>0){
                    JSONObject money = moneyList.get(0);
                    totalAccount = money.getBigDecimal("value");
                    if(totalAccount.compareTo(BigDecimal.ZERO)>0){
                        saveType = "fundPayment";
                        paramMap.put("tradetype_code", defaultDataService.TRADE_TYPE_CODE[0]); //交易类型(报销付款)
                    }else if(totalAccount.compareTo(BigDecimal.ZERO)<0){
                        saveType = "fundCollection";
                        paramMap.put("tradetype_code", defaultDataService.TRADE_TYPE_CODE[3]); //交易类型(其他付款)
                        totalAccount=totalAccount.abs();
                    }else{
                        throw new RuntimeException("{error:\"费用报销审批单:"+businessId+"中未金额输入为0！！！\"}");
                    }
                }
                List<JSONObject> TWO_CWFREE = jsonArray.stream()
                        .filter(json -> DingDingComponent.TWO_CWFREE.equals(json.getStr("id")))
                        .collect(Collectors.toList());
                if(TWO_CWFREE.size()>0){
                    JSONObject CWFREE = TWO_CWFREE.get(0);
                    if(CWFREE.containsKey("value")){
                        expenseitem_code=CWFREE.getStr("value");
                    }
                }
                List<JSONObject> TWO_YFFREE = jsonArray.stream()
                        .filter(json -> DingDingComponent.TWO_YFFREE.equals(json.getStr("id")))
                        .collect(Collectors.toList());
                if(TWO_YFFREE.size()>0){
                    JSONObject YFFREE = TWO_YFFREE.get(0);
                    if(YFFREE.containsKey("value")){
                        expenseitem_code=YFFREE.getStr("value");
                    }
                }
                List<JSONObject> TWO_XZFREE = jsonArray.stream()
                        .filter(json -> DingDingComponent.TWO_XZFREE.equals(json.getStr("id")))
                        .collect(Collectors.toList());
                if(TWO_XZFREE.size()>0){
                    JSONObject XZFREE = TWO_XZFREE.get(0);
                    if(XZFREE.containsKey("value")){
                        expenseitem_code=XZFREE.getStr("value");
                    }
                }
                List<JSONObject> TWO_YXFREE = jsonArray.stream()
                        .filter(json -> DingDingComponent.TWO_YXFREE.equals(json.getStr("id")))
                        .collect(Collectors.toList());
                if(TWO_YXFREE.size()>0){
                    JSONObject YXFREE = TWO_YXFREE.get(0);
                    if(YXFREE.containsKey("value")){
                        expenseitem_code=YXFREE.getStr("value");
                    }
                }
                List<JSONObject> TWO_RSFREE = jsonArray.stream()
                        .filter(json -> DingDingComponent.TWO_RSFREE.equals(json.getStr("id")))
                        .collect(Collectors.toList());
                if(TWO_RSFREE.size()>0){
                    JSONObject RSFREE = TWO_RSFREE.get(0);
                    if(RSFREE.containsKey("value")){
                        expenseitem_code=RSFREE.getStr("value");
                    }
                }
                List<JSONObject> TWO_SHFREE = jsonArray.stream()
                        .filter(json -> DingDingComponent.TWO_SHFREE.equals(json.getStr("id")))
                        .collect(Collectors.toList());
                if(TWO_SHFREE.size()>0){
                    JSONObject SHFREE = TWO_SHFREE.get(0);
                    if(SHFREE.containsKey("value")){
                        expenseitem_code=SHFREE.getStr("value");
                    }
                }
                fundPaymentBItem.put("expenseitem_code",expenseitem_code); //费用项目
                fundPaymentBItem.put("description",expenseitem_code); //摘要

                //设置单据创建时间
                processInstance.setCreate(jsonObject.getJSONObject("result").getStr("create"));
                processInstance.setUpdateDate(new Date());
                processInstance.setBusinessId(businessId);

                //费用明细
                List<JSONObject> fymxList = jsonArray.stream()
                        .filter(json -> DingDingComponent.FYMX.equals(json.getStr("id")))
                        .collect(Collectors.toList());
                if(fymxList.size()>0){
                    JSONObject fymx = fymxList.get(0);
                    List<JSONObject> itemJSONList = fymx.getJSONArray("value").toList(JSONObject.class);
                    List<JSONObject> jsonRowValueSE = itemJSONList.get(0).getJSONArray("rowValue").toList(JSONObject.class);
                    BigDecimal se=BigDecimal.ZERO;
                    if (defaultDataService.ORG_NAME.contains(orgName)){
                        List<JSONObject> FYMXSE = jsonRowValueSE.stream()
                                .filter(json -> DingDingComponent.FYMXSE.equals(json.getStr("key")))
                                .collect(Collectors.toList());
                        if(FYMXSE.size()>0){
                            List<BigDecimal> seList = FYMXSE.get(0).getJSONArray("value").toList(BigDecimal.class);
                            if(!seList.isEmpty()){
                                totalSE=seList.get(0);
                            }
                        }
                    }
                    for (int j = 0; j < itemJSONList.size(); j++) {
                        //子表自定义特征参数
                        Map<String,Object> characterDefb=new HashMap<>();;
                        Map<String,Object> fundPaymentBItemTotal = new HashMap<>();
                        fundPaymentBItemTotal.putAll(fundPaymentBItem);
                        JSONArray jsonArrayRowValue = itemJSONList.get(j)
                                .getJSONArray("rowValue");
                        //获取部门编码
                        String deptCode = jsonArrayRowValue.getJSONObject(0)
                                .getJSONArray("extendValue")
                                .getJSONObject(0)
                                .getStr("id");
                        //获取报销金额
                        double oriSum = Math.abs(jsonArrayRowValue.getJSONObject(1).getDouble("value"));
                        if (totalSE.compareTo(BigDecimal.ZERO)>0 && defaultDataService.ORG_NAME.contains(orgName)){
                            BigDecimal oriBigDecimal = new BigDecimal(Double.toString(oriSum));
                            if(itemJSONList.size()==1){
                                characterDefb.put("SE",totalSE); //税额
                                characterDefb.put("WSJE",oriBigDecimal.subtract(totalSE)); //未税金额
                            }else{
                                if (j == itemJSONList.size()-1 ){
                                    //最后一条数据的税额尾插法插入
                                    characterDefb.put("SE",lastSE); //税额
                                    characterDefb.put("WSJE",oriBigDecimal.subtract(lastSE)); //未税金额
                                }else {
                                    //该子表税额
                                    BigDecimal division = oriBigDecimal.divide(totalAccount, 10, RoundingMode.HALF_UP);
                                    BigDecimal resultSE = division.multiply(totalSE).setScale(2, RoundingMode.HALF_UP);
                                    lastSE=totalSE.subtract(resultSE);
                                    characterDefb.put("SE",resultSE); //税额
                                    characterDefb.put("WSJE",oriBigDecimal.subtract(resultSE)); //未税金额
                                }
                            }

                        }
                        fundPaymentBItemTotal.put("oriSum",oriSum); //付款金额
                        fundPaymentBItemTotal.put("dept_code",deptCode); //费用承担部门
                        fundPaymentBItemTotal.put("characterDefb",characterDefb); //特征字段(税额,未税金额)
                        fundPaymentBList.add(fundPaymentBItemTotal);  //子表参数集合
                    }
                }
                //费用明细
                List<JSONObject> skbankList = jsonArray.stream()
                        .filter(json -> DingDingComponent.SKBANK.equals(json.getStr("id")))
                        .collect(Collectors.toList());
                if(skbankList.size()>0){
                    JSONObject skbank = skbankList.get(0);
                    if (skbank.containsKey("extValue")){
                        JSONObject extValueJson = skbank.getJSONObject("extValue");
                        String identityType = extValueJson.getStr("identityType");
                        String name = extValueJson.getStr("name"); //账户名称
                        //结算方式判断
                        if ("CORP_BANK_CARD".equals(identityType) || "PERSONAL_BANK_CARD".equals(identityType)){
                            paramMap.put("settlemode_code",defaultDataService.SETTLEMODE_CODE[0]); //结算方式(银行转账)
                            String cardNo = extValueJson.getStr("cardNo"); //收款人银行账号
                            String bankId = "";
                            String bankTypeId = "";
                            String linenumber = "";
                            //获取银行网点信息
                            String instBranchName1 = extValueJson.getStr("instBranchName");
                            if (instBranchName1 ==null || instBranchName1.isEmpty()){
                                logger.error("单据{}中银行网点未填写",businessId);
                            }else {
                                JSONObject instBranchName = ysDataGetService.getBankDotList(instBranchName1);
                                if ("200".equals(instBranchName.getStr("code"))){
                                    JSONArray jsonArray1 = instBranchName.getJSONObject("data").getJSONArray("recordList");
                                    if (!jsonArray1.isEmpty()){
                                        JSONObject bankDetails = jsonArray1.getJSONObject(0);
                                        bankId = bankDetails.getStr("id"); //银行网点id
                                        bankTypeId = bankDetails.getStr("bank"); //银行类别id
                                        linenumber = bankDetails.getStr("linenumber"); //联行号
                                    }else{
                                        throw new RuntimeException("{error:\"获取付款单ys银行网点编码失败-资金调拨审批单"+businessId+"中银行网点编码不存在！！！\"}");
                                    }
                                }
                            }
                            for (Map<String,Object> fundPaymentB : fundPaymentBList){
                                fundPaymentB.put("oppositeobjectname",name); //收款单位名称
                                fundPaymentB.put("oppositeaccountno",cardNo); //收款方银行账号
                                fundPaymentB.put("oppositeaccountname",name);//收款方账户名称。
                                fundPaymentB.put("oppositebankaddr",bankId); //收款方开户行名称id
                                fundPaymentB.put("oppositebanklineno",linenumber); //收款方银行联行号
                                fundPaymentB.put("oppositebankType",bankTypeId); //收款方银行类别
                                fundPaymentB.put("settlemode_code",defaultDataService.SETTLEMODE_CODE[0]); //结算方式(银行转账)
                            }
                            //logger.info("转入银行账号:{}",cardNo);
                        }else if ("ALIPAY_ACCOUNT".equals(identityType)){
                            for (Map<String,Object> fundPaymentB : fundPaymentBList){
                                fundPaymentB.put("oppositeobjectname",name); //收款单位名称
                                fundPaymentB.put("oppositeaccountname",name);//收款方账户名称。
                                fundPaymentB.put("settlemode_code",defaultDataService.SETTLEMODE_CODE[1]); //结算方式(支付宝2)
                            }
                            //结算方式为支付宝支付-无需设置账号
                            paramMap.put("settlemode_code",defaultDataService.SETTLEMODE_CODE[1]); //结算方式(支付宝2)
                        }
                    }
                }
                //遍历组件里的value值
                JSONObject jsonObjectResponse;
                //发送请求保存到ys中
                if ("fundCollection".equals(saveType)) {
                    //保存到资金收款单中
                    paramMap.put("FundCollection_b", fundPaymentBList); //将子表放入到主表中
                    dataMap.put("data", paramMap);
                    logger.info(JSONUtil.toJsonStr(dataMap));
                    //最终封装的数据
                    jsonObjectResponse = defaultDataService.sendPostToSaveFundCollection(dataMap); //发送请求
//                    //处理响应结果
                    if (jsonObjectResponse.getStr("code").equals("200")){
                        //保存成功，数据库中修改标记
                        JSONObject data = jsonObjectResponse.getJSONObject("data");
                        String id = data.getStr("id");
                        Map<String,Object> submit=new HashMap<>();
                        Map<String,Object> submitdata=new HashMap<>();
                        submitdata.put("id",id);
                        submit.put("data",submitdata);
                        jsonObjectResponse = defaultDataService.sendPostToSubmit(submit); //发送请求

                    }
                    defaultDataService.processResponseResults(jsonObjectResponse,businessId,saveType,processInstance);
                }else {
                    //保存到资金付款单中
                    paramMap.put("FundPayment_b", fundPaymentBList); //将子表放入到主表中
                    dataMap.put("data", paramMap); //最终封装的数据
                    logger.info(JSONUtil.toJsonStr(dataMap));
                    jsonObjectResponse = defaultDataService.sendPostToSaveFundPayment(dataMap); //发送请求
//                    //处理响应结果
                    defaultDataService.processResponseResults(jsonObjectResponse, businessId,saveType,processInstance);
                }
                ysJsonResponseList.add(jsonObjectResponse.getJSONObject("data"));
                //ysJsonResponseList.add(new JSONObject(dataMap));
            }catch (Exception e){
                defaultDataService.InsertLogger(businessId,"0",e.getMessage(),"panzhinew1");
                e.printStackTrace();
                logger.error("费用报销错误信息:{}",e.getMessage());
                logger.info("--------------------------------------------------------------------------------");
            }
        }
        return ysJsonResponseList;
    }

    public static String dealTime(String oldTime){

        OffsetDateTime offsetDateTime = OffsetDateTime.parse(oldTime);
        // 定义目标格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 格式化为指定格式
        String formattedTime = offsetDateTime.format(formatter);

        return formattedTime;
    }



}
